package com.boyicloud.exchangeserver.web.controller

import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component
import java.io.IOException
import java.util.concurrent.CopyOnWriteArraySet
import javax.websocket.*
import javax.websocket.server.ServerEndpoint

/**
 * @author lengchunyun
 */
@Component
@ServerEndpoint("/status")
class WebSocketServer {


    val log: Logger = LoggerFactory.getLogger(WebSocketServer::class.java)

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private var session: Session? = null

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    fun onOpen(session: Session?) {
        this.session = session
        //加入set中
        webSocketSet.add(this)
        addOnlineCount() //在线数加1
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    fun onClose() {
        //从set中删除
        webSocketSet.remove(this)
        subOnlineCount() //在线数减1
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    fun onMessage(message: String) {
        //群发消息
        for (item in webSocketSet) {
            try {
                item.sendMessage(message)
            } catch (e: IOException) {
                log.warn("error:{}", e.message, e)
            }
        }
    }

    /**
     * @param error 错误信息
     */
    @OnError
    fun onError(error: Throwable) {
        log.error("发生错误: ${error.message}", error)
    }

    /**
     * 实现服务器主动推送
     */
    @Throws(IOException::class)
    private fun sendMessage(message: String) {
        session!!.basicRemote.sendText(message)
    }

    companion object {
        /**
         * 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
         */
        @get:Synchronized
        private var onlineCount = 0

        /**
         * concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
         */
        private val webSocketSet: CopyOnWriteArraySet<WebSocketServer> = CopyOnWriteArraySet<WebSocketServer>()

        private val log: Logger = LoggerFactory.getLogger(WebSocketServer::class.java)

        /**
         * 群发自定义消息
         */
        fun sendInfo(message: String) {
            for (item in webSocketSet) {
                try {
                    item.sendMessage(message)
                } catch (e: IOException) {
                    log.warn("error:{}", e.message, e)
                }
            }
        }

        @Synchronized
        private fun addOnlineCount() {
            onlineCount++
        }

        @Synchronized
        private fun subOnlineCount() {
            onlineCount--
        }
    }
}